﻿using System;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace Toybox.NicoSharp.Live.Alert
{
	using Primitives;
	using Logger;

	/// <summary>
	/// Alert Client クラス
	/// </summary>
	public partial class AlertClient : AbstractMessageClient
	{

		#region Events

		/// <summary>
		/// AlertStatus 受信イベント
		/// </summary>
		public event EventHandler<AlertStatus> RecvAlertStatus;

		/// <summary>
		/// LiveInfo 受信イベント
		/// </summary>
		public event EventHandler<LiveInfo> RecvLiveInfo;

		/// <summary>
		/// AlertStatus 受信
		/// </summary>
		/// <param name="status"></param>
		protected virtual void OnRecvAlertStatus(AlertStatus status)
		{
			if (RecvAlertStatus != null)
				RecvAlertStatus(this, status);
		}

		/// <summary>
		/// LiveInfo 受信
		/// </summary>
		/// <param name="info"></param>
		protected virtual void OnRecvLiveInfo(LiveInfo info)
		{
			if (RecvLiveInfo != null)
				RecvLiveInfo(this, info);
		}

		#endregion Events


		#region Public Methods

		/// <summary>
		/// 接続開始 (Thread)
		/// </summary>
		/// <param name="count">さかのぼるコメント数</param>
		public void ThreadStart(int count = 0)
		{
			this.ThreadStop();

			this.InnerThread = new Thread(new ThreadStart(() =>
			{
				this.Start(count);
			}));
			this.InnerThread.Start();
		}

		/// <summary>
		/// 接続開始 (Task)
		/// </summary>
		/// <param name="count">さかのぼるコメント数</param>
		public void TaskStart(int count = 0)
		{
			this.TaskStop();

			this.InnerTask = Task.Factory.StartNew(() =>
			{
				this.Start(count);
			});
		}

		/// <summary>
		/// 接続開始
		/// </summary>
		/// <param name="count">さかのぼるコメント数</param>
		public void Start(int count = 0)
		{
			base.State = ConnectionState.Connecting;
			this.OnConnecting(EventArgs.Empty);

			#region アラート情報取得

			AlertStatus status;
			try
			{
				status = AlertStatus.Get();
			}
			catch (Exception ex)
			{
				TraceLogger.WriteLine(ex.ToString());
				base.State = ConnectionState.Disconnected;
				return;
			}

			this.OnRecvAlertStatus(status);

			// エラー
			if (status.status != "ok")
			{
				base.State = ConnectionState.Disconnected;
				return;
			}

			#endregion

			base.Connect(status.ms.addr, status.ms.port, status.ms.thread, count);
		}

		#endregion Public Methods

		#region Override Methods

		/// <summary>
		/// メッセージ解析メソッド
		/// </summary>
		/// <param name="message"></param>
		protected override void DeserializeMessage(string message)
		{
			if (message.StartsWith("<chat") && message.EndsWith("</chat>"))
			{
				Match match = Regex.Match(message, ">(?<live>.*?),(?<com>.*?),(?<user>.*?)<");
				if (match.Success)
				{
					var info = new LiveInfo()
					{
						Live = match.Groups["live"].Value,
						Com = match.Groups["com"].Value,
						User = match.Groups["user"].Value,
					};

					this.OnRecvLiveInfo(info);
				}
			}
		}

		#endregion Override Methods

	}
}